package org.puresilk.android.insults;

import org.json.JSONException;
import org.json.JSONObject;
import org.puresilk.android.db.Db;
import org.puresilk.android.net.HttpException;
import org.puresilk.android.net.HttpHandler;
import org.puresilk.android.net.HttpRequest;
import org.puresilk.android.net.HttpResponse;
import org.puresilk.android.util.Logger;

import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.ListActivity;
import android.app.ProgressDialog;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.database.Cursor;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CursorAdapter;
import android.widget.SimpleCursorAdapter;

public class ExcuseMe extends ListActivity {
	private ProgressDialog pDlg = null;
	private static final Logger logger = Logger.getInstance("ExcuseMe");
	private Db db;
	
	/**
	 * Basic Implementation of httpHandler from puresilk lib
	 * onRequestStart is where you would insert your progress dialog.
	 * Every Method should dismiss progress dialog except for onResponseProgress
	 */
	HttpHandler pHandler = new HttpHandler() {
		
		@Override
		public void onResponseReady(HttpResponse resp) {
			pDlg.dismiss();
			JSONObject json = resp.getJSONResults();
			String insult = null;
			try {
				insult = json.getString(getString(R.string.jsonValue));
				alertMessage(insult);
				logger.debug(insult);
				
				// do accounting
				track(insult);
				fillData();
				
			} catch (JSONException e) {
				logger.error(getString(R.string.jsonError), e);
			}
		}
		
		@Override
		public void onResponseProgress(String message) {
			logger.info(message);
		}
		
		@Override
		public void onResponseError(HttpException er) {
			pDlg.dismiss();
			logger.error(getString(R.string.httpError), er);
		}
		
		@Override
		public void onRequestStart() {
			pDlg = ProgressDialog.show(ExcuseMe.this, getString(R.string.alrtTitle), getString(R.string.alrtMessage),true,true);
		}

		@Override
		public void onWriteProgress(int bytesWritten) {}
	};
	
	/**
	 * Alert Builder to display json string passed in
	 * @param message
	 */
	private void alertMessage(String message){
		AlertDialog.Builder builder = new Builder(this);
		builder.setMessage(message);
		builder.setCancelable(true);
		
		builder.setPositiveButton(getString(R.string.alrtConfirm), new DialogInterface.OnClickListener() {
		
			public void onClick(DialogInterface dialog, int which) {
				dialog.cancel();
				
			}
		});
		builder.create();
		builder.show();
	}

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        db = new Db(new org.puresilk.android.db.Context(this.getResources().getStringArray(R.array.tracker)));
    	db.open(this);
        // check settings for new install or upgrade
        checkSettings();
        
        setContentView(R.layout.main);
        final String url = getString(R.string.url);
        final String data = getString(R.string.data);
        fillData();
        /*
         * Ties button1 from main.xml to onClickListener
         */
        Button pokeBtn = (Button) findViewById(R.id.button1);
        pokeBtn.setOnClickListener(new OnClickListener() {
			
			public void onClick(View v) {
				
				/*
				 * url = base url to fire rpc
				 * data = action ie. action=test.Poke
				 * int = how you want data back. ie. json, xml
				 */
				try {
					HttpRequest rpc = new HttpRequest(url, data, HttpRequest.JSON_REQUEST_TYPE);
					rpc.fetch(ExcuseMe.this, pHandler);
				}
				catch (HttpException ex) {
					logger.debug(getString(R.string.httpError)+ ex );
				}
			}
		});
    }
    
    @Override
    public void onDestroy(){
    	super.onDestroy();
    	logger.debug("Shutting down db connection");
    	db.close();
    }
    
    /**
     * Default reset just dumps tracker
     * table
     */
    public void reset() {
    	reset(false);
    }
    
    /**
     * reset counters for insults and 
     * optionally reset application
     * and database versioning to 1.
     */
    private void reset(boolean all){
    	// remove all records
    	db.delete(null);
    	
    	// if flag is set, reset versions
    	if(all){
    		// get shared preferences
    		SharedPreferences ss = getSharedPreferences(getString(R.string.sharedsettings), Context.MODE_PRIVATE);
    		Editor ed = ss.edit();
    		
    		// reset versions
			ed.putInt(getString(R.string.dbVersionLabel), 1);
			ed.putInt(getString(R.string.appVersionLabel), 1);
			ed.commit();
    	}
    }
    
    /**
     * Version checking. 
     */
    private void checkSettings(){
		// first, check db for create or upgrade
		SharedPreferences ss = getSharedPreferences(getString(R.string.sharedsettings), Context.MODE_PRIVATE);
		int curDbVer = Integer.parseInt(getString(R.string.dbVersion));
		int curAppVer = Integer.parseInt(getString(R.string.appVersion));
		int dbVer = ss.getInt(getString(R.string.dbVersionLabel), 0);
		int appVer = ss.getInt(getString(R.string.appVersionLabel), 0);
		int editSettings = 0;
		
		// check for reset request (dev)
		if (appVer < 0) {
			 //back to start
			reset(true);
			return;
		}
		
		Editor ed = ss.edit();
		
		// check for new install
		if(appVer == 0) {
			// init database
			Db.initialize(this, false);
			
			// update prefs
			editSettings++;
			ed.putInt(getString(R.string.dbVersionLabel), curDbVer);
			ed.putInt(getString(R.string.appVersionLabel), curAppVer);
		}
		
		if(appVer < curAppVer){
			editSettings++;
			ed.putInt(getString(R.string.appVersionLabel), curAppVer);
		}
		
		// check for db upgrades
		if(dbVer < curDbVer) {
			editSettings++;
			
			// upgrade db
			Db.upgrade(this);
			
			// update prefs
			ed.putInt(getString(R.string.dbVersion), curDbVer);
		}

		// save any changes
    	ed.commit();    	
    }

    /**
     * Count how many times we see each
     * insult.
     * 
     * @param insult
     */
    private void track(String insult) {
    	// SQL clause values
    	ContentValues cv = new ContentValues();
    	cv.put(getString(R.string.insult), insult);
    	ContentValues where = new ContentValues();
    	
    	// hunt for existing insult
    	Cursor cr = db.select(null,cv,null,null,null);
    	startManagingCursor(cr);
    	
    	// check to see if we found one
    	if (cr.moveToFirst()) {
    		// bump counter
    		int i = cr.getInt(cr.getColumnIndex(getString(R.string.count))) + 1;
    		
    		cv.remove(getString(R.string.insult));
    		cv.put(getString(R.string.count),new Integer(i));
    		
    		where.put(getString(R.string._id_text),cr.getInt(cr.getColumnIndex(getString(R.string._id_text))));
    		
    		// update count for this insult
    		db.update(cv, where);
    	}
    	else {
    		// insert new insult
    		logger.debug("First incident for " + insult);
    		
    		cv.put(getString(R.string.count),new Integer(1));
    		db.insert(cv);
    	}
	}
    
    private void fillData(){
		Cursor cr = db.select(null,null,null, null,null);
		startManagingCursor(cr);
		// the desired columns to be bound
		String[] columns = new String[]{getString(R.string.insult),getString(R.string.count)};
		
		// the XML defined views which the data will be bound to
		int[] to = new int[] {R.id.insult_entry, R.id.count_entry };
		
		// create the adapter using the cursor pointing to the desired data as well as the layout information
		CursorAdapter mAdapter = new SimpleCursorAdapter(this, R.layout.insult, cr, columns, to);
		// set this adapter as your ListActivity's adapter
		
		setListAdapter(mAdapter);
	}
    /**
	 * Menu inflater
	 * creates menu object and loads intents for each item
	 */
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        boolean result = super.onCreateOptionsMenu(menu);
        menu.add(0, 1, 0, R.string.menu_clear_text);
        menu.add(0, 2, 0, R.string.menu_about_text);
        return result;
    }
    
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case 1:
            reset(true);
            fillData();
            return true;
        case 2:
        	//TODO launch eula like about message of puresilk 30 seconds highlight reel of app with url to site for bugs and new releases.
        	alertMessage("www.pure-silk.org");
        	return true;
        }
       
        return super.onOptionsItemSelected(item);
    }
}